package router

import (
	"github.com/golang-jwt/jwt/v4"
	"github.com/joho/godotenv"
	echojwt "github.com/labstack/echo-jwt/v4"
	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
	"net/http"
	"os"
	"path/filepath"
	"time"
	"turingApi/conf"
	"turingApi/control"
)

// Init 入口
func Init() *echo.Echo {
	conf.Logger.Info("app initializing...")
	err := godotenv.Load()
	if err != nil {
		conf.Logger.Error("Error while load env: ", err)
	}

	conf.Logger.Info("Use sensitive words DIR ", *control.DictDir)
	if err := InitMatchService(*control.DictDir); err != nil {
		conf.Logger.Error("Init sensitive dict error: ", err.Error())
	}

	engine := echo.New()           // 实例化echo
	engine.Renderer = initRender() // 初始渲染引擎

	//engine.Use(middleware.Logger())
	engine.Use(zapLogger)
	engine.Use(middleware.Recover())
	engine.Use(middleware.CORSWithConfig(middleware.CORSConfig{
		AllowOrigins: []string{"*"},
		AllowMethods: []string{echo.GET, echo.PUT, echo.POST, echo.DELETE},
	}))
	engine.HideBanner = false                  // 不显示横幅
	engine.HTTPErrorHandler = HTTPErrorHandler // 自定义错误处理
	engine.Debug = conf.App.IsDev()            // 运行模式 - echo框架好像没怎么使用这个

	rateConfig := middleware.RateLimiterConfig{
		Skipper: middleware.DefaultSkipper,
		Store: middleware.NewRateLimiterMemoryStoreWithConfig(
			middleware.RateLimiterMemoryStoreConfig{Rate: 2, Burst: 3, ExpiresIn: 3 * time.Minute},
		),
		IdentifierExtractor: func(ctx echo.Context) (string, error) {
			id := ctx.RealIP()
			return id, nil
		},
		ErrorHandler: func(context echo.Context, err error) error {
			return context.JSON(http.StatusForbidden, nil)
		},
		DenyHandler: func(context echo.Context, identifier string, err error) error {
			return context.JSON(http.StatusTooManyRequests, middleware.ErrRateLimitExceeded.Message)
		},
	}
	engine.Use(middleware.RateLimiterWithConfig(rateConfig))

	engine.Static("/dist", "dist")     // 静态目录 - 后端专用
	engine.Static("/static", "static") // 静态目录

	engine.GET("/", func(c echo.Context) error {
		return c.Render(200, "ws.html", "你好")
	})

	engine.GET("/ws/v2/:openid/:to", control.WsHandlerV2)
	engine.POST("/login/:code", control.LoginHandler)

	auth := engine.Group("/auth")

	jwtConfig := echojwt.Config{
		SigningKey:  []byte(conf.SecretKey),
		TokenLookup: "header:Authorization:Bearer ,query:token,cookie:jwt",
		NewClaimsFunc: func(c echo.Context) jwt.Claims {
			return new(control.JwtCustomClaims)
		},
	}

	auth.Use(echojwt.WithConfig(jwtConfig))
	authenticatedRouter(auth) // 注册分组路由

	return engine
}

func InitMatchService(dictDir string) error {
	var files []string
	//只关注rootDir下面的文件，暂时不支持子文件夹的形式
	err := filepath.Walk(dictDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {

			conf.Logger.Warnf("load %s fail %s", dictDir, err.Error())
			return nil
		}

		if !info.IsDir() {
			files = append(files, info.Name())
		}
		return nil
	})

	if err != nil {
		return err
	}

	var words []string
	for _, file := range files {
		if w, err := readWordsFromFile(dictDir + "/" + file); err == nil {
			conf.Logger.Infof("load senvitive files  %s words size %d", dictDir+"/"+file, len(w))
			words = append(words, w...)
		} else {
			return err
		}
	}

	control.MatchService.Build(words)
	return nil
}
